import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.session.SessionDataSet.DataIterator;
import org.apache.iotdb.session.pool.SessionDataSetWrapper;
import org.apache.iotdb.session.pool.SessionPool;
import org.apache.iotdb.session.template.MeasurementNode;
import org.apache.iotdb.session.template.Template;
import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;

public class DemePool {
    private static int eventNameIndex;
    private static final String ROOT_SG1_D1 = "root.sg1.d1";
    private static final String ROOT_DVID = "root.dvid";
    private static final String LOCAL_HOST = "ol";
    private static SessionPool sessionPool;
    private static ExecutorService service;
    private static int threadIndex = 22;
    private final static int ID_RANG = 10000 * 20; // 每个线程负责 10W ID
    private final static int EVENT_CNT = 10; // 每个ID 插入多少事件
    // private final static String HOST = "172.27.255.240";
    private final static String HOST = "172.27.255.241";
    private final static String sqlFormat = "SELECT * FROM root.dvid.";

    public static void main(String[] args) throws IoTDBConnectionException, InterruptedException, IOException {
        sessionPool = new SessionPool.Builder()
                .host(HOST)
                .port(6667)
                .user("root")
                .password("root")
                .maxSize(30)
                .build();

        service = Executors.newFixedThreadPool(10);

        createTemplate();

        // queryByRowRecord();

        // queryByIterator();

        for (int i = 0; i < 8; i++) {
            service.submit(
                    () -> {
                        queryByIterator();
                    });
        }

        // service.shutdown();
        service.wait();

        sessionPool.close();
        // service.shutdown();
    }

    private static void createTemplate() {
        try {
            // setStorageGroup
            sessionPool.setStorageGroup("root.dvid");

            // create template
            Template template = new Template("dv_temp", false);
            MeasurementNode mNodeS1 = new MeasurementNode("ptt", TSDataType.INT64, TSEncoding.RLE,
                    CompressionType.SNAPPY);
            MeasurementNode mNodeS2 = new MeasurementNode("app_duration", TSDataType.INT64, TSEncoding.RLE,
                    CompressionType.SNAPPY);
            MeasurementNode mNodeS3 = new MeasurementNode("event_name", TSDataType.TEXT, TSEncoding.DICTIONARY,
                    CompressionType.SNAPPY);

            template.addToTemplate(mNodeS1);
            template.addToTemplate(mNodeS2);
            template.addToTemplate(mNodeS3);
            sessionPool.createSchemaTemplate(template);

            // set template
            sessionPool.setSchemaTemplate("dv_temp", "root.dvid");
        } catch (StatementExecutionException e) {
            // e.printStackTrace();
        } catch (IoTDBConnectionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private static void insertRecord()
            throws IoTDBConnectionException, StatementExecutionException {
        long baseTime = System.currentTimeMillis();
        long inserted = 0;
        int threadIndex = getThreadIndex();
        int IDBeg = threadIndex * ID_RANG;
        int IDEnd = IDBeg + ID_RANG;
        long startTime = System.currentTimeMillis();

        for (long eventIndex = 0; eventIndex < EVENT_CNT; eventIndex++) {
            long time = eventIndex * 1000 + baseTime;
            long ptt = eventIndex * 1000 + 1399931004;
            for (int id = IDBeg; id < IDEnd; id++) {
                String deviceId = ROOT_DVID + "." + id;
                List<String> measurements = new ArrayList<>();
                List<TSDataType> types = new ArrayList<>();

                measurements.add("ptt");
                measurements.add("app_duration");
                measurements.add("event_name");

                types.add(TSDataType.INT64);
                types.add(TSDataType.INT64);
                types.add(TSDataType.TEXT);

                // List<String> values = new ArrayList<>();
                List<Object> values = new ArrayList<>();
                values.add(ptt);
                values.add(eventIndex + id);
                values.add(getEventName());

                sessionPool.insertRecord(deviceId, time, measurements, types, values);
                // sessionPool.insertAlignedRecord(deviceId, time, measurements, values);

                inserted++;

                if (inserted % 10000 == 0) {
                    System.out.println(
                            System.currentTimeMillis() + "\t" + threadIndex + " inserted:" + inserted + "\tid:" + id);
                    // System.out.println("qpms:" + (10000 % (System.currentTimeMillis() -
                    // startTime)));
                    // startTime = System.currentTimeMillis();
                }
            }
        }
        return;
    }

    private static void queryByRowRecord() {
        for (int i = 0; i < 1000; i++) {
            SessionDataSetWrapper wrapper = null;

            try {
                wrapper = sessionPool.executeQueryStatement(sqlFormat + i);
                // System.out.println(wrapper.getColumnNames());
                // System.out.println(wrapper.getColumnTypes());
                while (wrapper.hasNext()) {
                    // System.out.println(wrapper.next());
                }
            } catch (IoTDBConnectionException | StatementExecutionException e) {
                e.printStackTrace();
            } finally {
                // remember to close data set finally!
                sessionPool.closeResultSet(wrapper);
            }
        }
    }

    private static void queryByIterator() {
        long inserted = 0;
        int threadIndex = getThreadIndex();
        int IDBeg = threadIndex * ID_RANG;
        int IDEnd = IDBeg + ID_RANG;
        long startTime = System.currentTimeMillis();
        SessionDataSetWrapper wrapper = null;
        for (int i = IDBeg; i < IDEnd; i++) {
            try {
                wrapper = sessionPool.executeQueryStatement(sqlFormat + i);
                // get DataIterator like JDBC
                DataIterator dataIterator = wrapper.iterator();
                // System.out.println(wrapper.getColumnNames());
                // System.out.println(wrapper.getColumnTypes());
                while (dataIterator.next()) {
                    // StringBuilder builder = new StringBuilder();
                    // for (String columnName : wrapper.getColumnNames()) {
                    // builder.append(dataIterator.getString(columnName) + " ");
                    // }
                    // System.out.println(builder);
                }
            } catch (IoTDBConnectionException | StatementExecutionException e) {
                e.printStackTrace();
            } finally {
                // remember to close data set finally!
                sessionPool.closeResultSet(wrapper);
            }
        }
    }

    private synchronized static int getThreadIndex() {
        return threadIndex++;
    }

    private static String getEventName() {

        String eventName[] = {
                "ZDEN_AppStart",
                "ZDEN_PageIn",
                "screenName",
                "screenName",
                "ZDEN_DeviceInfo",
                "screenName",
                "screenName",
                "screenName",
                "screenName",
                "ZDEN_UserChange",
                "ZDEN_AppStart",
                "ZDEN_PageIn",
                "screenName",
                "ZDEN_DeviceInfo",
                "screenName",
                "screenName",
                "screenName",
                "screenName",
                "screenName",
                "screenName",
                "ZDEN_UserChange",
                "ZDEN_AppStart",
                "ZDEN_PageIn",
                "ZDEN_DeviceInfo",
                "screenName",
                "screenName",
                "screenName",
                "screenName",
                "screenName",
                "screenName",
                "ZDEN_DeviceInfo",
                "ZDEN_DeviceInfo",
                "ZDEN_DeviceInfo",
                "screenName",
                "screenName",
                "screenName",
                "ZDEN_Onload",
                "ZDEN_NetworkRequest",
                "ZDEN_Click",
                "ZDEN_Typing",
                "ZDEN_Typing",
                "ZDEN_Typing",
                "ZDEN_Typing",
                "ZDEN_NetworkRequest",
                "ZDEN_Typing",
                "ZDEN_NetworkRequest",
                "ZDEN_Typing",
                "ZDEN_Typing",
                "ZDEN_Resize",
                "ZDEN_Typing",
                "ZDEN_Typing",
                "ZDEN_Typing",
                "ZDEN_Typing",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_Onload",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_Typing",
                "ZDEN_Click",
                "buttonClick_next_signInUserName",
                "screenName",
                "ZDEN_NetworkRequest",
                "ZDEN_PageJumpH5",
                "ZDEN_NetworkRequest",
                "ZDEN_Typing",
                "ZDEN_Typing",
                "ZDEN_Resize",
                "ZDEN_Typing",
                "ZDEN_Typing",
                "ZDEN_Click",
                "buttonClick_signIn_signInPassword",
                "screenName",
                "ZDEN_NetworkRequest",
                "signInFailure",
                "ZDEN_Resize",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_PageJumpManual",
                "screenName",
                "ZDEN_GoBack",
                "ZDEN_Resize",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_Onload",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_NetworkRequest",
                "ZDEN_Typing",
                "ZDEN_Click",
                "ZDEN_NetworkRequest",
                "ZDEN_Typing",
                "ZDEN_Resize",
                "ZDEN_Typing"
        };

        return eventName[eventNameIndex++ % eventName.length];
    }
}
